﻿using System.Linq;
using System.Web.Mvc;
using Dexter.Domain.Model;
using Dexter.Logger.Contracts;
using Dexter.Services;
using Dexter.Web.Mvc.Controllers.Backoffice.Extensions;
using Dexter.Web.Mvc.Extensions;
using Dexter.Web.Mvc.Filters;
using Dexter.Web.Mvc.ViewModel.Backoffice.Binders;
using Dexter.Web.Mvc.ViewModel.Backoffice.ViewsData.PageController;
using Dexter.Web.Routing;
using Dexter.Web.Utils;

namespace Dexter.Web.Mvc.Controllers.Backoffice {
	[Authorize ( Roles = "Administrator" )]
	[DexterCallFilter ( false )]
	public class PageController : BackOfficeControllerBase {
		readonly IPageService pageService;
		readonly IRoutingService routingService;

		/// <summary>
		/// Initializes a new instance of the <see cref="PageController"/> class.
		/// </summary>
		/// <param name="configurationService">The configuration service.</param>
		/// <param name="webUtils">The web utils.</param>
		/// <param name="logger">The logger.</param>
		/// <param name="urlBuilder">The URL builder.</param>
		/// <param name="contactService">The contact service.</param>
		/// <param name="pageService">The page service.</param>
		/// <param name="routingService">The routing service.</param>
		public PageController ( IConfigurationService configurationService , IWebUtils webUtils , ILogger logger , IUrlBuilder urlBuilder , IContactService contactService , IPageService pageService , IRoutingService routingService ) : base ( configurationService , webUtils , logger , urlBuilder , contactService ) {
			this.pageService = pageService;
			this.routingService = routingService;
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult Index ( int? page, string username ) {
			int pageIndex = page ?? 1;

			pageIndex--;

			var data = base.GetViewData ( new PageListViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );

			data.Pages = pageService.GetPages ( pageIndex , 20 ).ToDtos();

			return View ( data );
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult Editor ( int? id ) {
			var data = base.GetViewData ( new PageEditorViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );
			data.Pages = !id.HasValue
			             	? pageService.GetPagesStructure ( ).ToDtos()
			             	: pageService.GetPagesStructure ( ).Where ( x => x.Id != id.Value ).ToDtos();

			data.Page = id.HasValue
			       	? pageService.GetByKeyWithParent ( id.Value ).ToPageBinder ( )
			       	: PageBinder.EmptyInstance ( );

			return View ( data );
		}

		[ValidateAntiForgeryToken]
		[AcceptVerbs ( HttpVerbs.Post )]
		public ActionResult Editor (  int? id, PageBinder page ) {

			if (!ModelState.IsValid) {
				var data = base.GetViewData ( new PageEditorViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );
				data.Pages = !id.HasValue
				            	? pageService.GetPagesStructure ( ).ToDtos()
				            	: pageService.GetPagesStructure ( ).Where ( x => x.Id != id.Value ).ToDtos();
				data.Page = page;

				return View ( data );
			}

			Page item;
			Page parentPage = null;

			if(page.ParentPageID.HasValue && page.ParentPageID.Value > 0)
				parentPage = pageService.GetByKeyWithParent ( page.ParentPageID.Value , true );

			if (page.Id > 0) {
				item = pageService.GetByKeyWithParent ( page.Id , true);
				item.Parent = parentPage;

				page.ToPage ( item );

				pageService.Update ( item );
			}
			else {
				item = Page.CreateNewPage ( page.Title, page.FormattedBody );
				item.Parent = parentPage;

				page.ToPage ( item );
				
				pageService.Save ( item );
			}

			routingService.UpdateRoutes ( );

			return this.ReturnFeedback ( MessageType.Positive, "PageSaved", base.UrlBuilder.BackOffice.PageList );
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult ConfirmDelete ( int id ) {
			if (id < 1)
				return HttpNotFound ( );

			var data = base.GetViewData ( new PageDeleteViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );
			data.Page = pageService.GetByKeyWithParent ( id );

			return View ( data );
		}

		[AcceptVerbs ( HttpVerbs.Post )]
		[ValidateAntiForgeryToken]
		public ActionResult Delete ( int id ) {
			pageService.Delete ( id );

			routingService.UpdateRoutes (  );

			return this.ReturnFeedback ( MessageType.Positive, "PageDeleted", base.UrlBuilder.BackOffice.PageList );
		}
	}
}
